#include <iomanip>
#include <iostream>
#include <openssl/evp.h>
#include <openssl/rand.h>
#include <sstream>
#include <string>
#include <vector>

using namespace std;

// 字符串转16进制
string toHex(const vector<unsigned char>& data)
{
    stringstream ss;
    for (auto c : data) {
        ss << hex << setw(2) << setfill('0') << (int)c;
    }
    return ss.str();
}

// 16进制转字节数组
vector<unsigned char> hexToBytes(const string& hex)
{
    vector<unsigned char> bytes;
    for (size_t i = 0; i < hex.length(); i += 2) {
        string byteString = hex.substr(i, 2);
        unsigned char byte = (unsigned char)strtol(byteString.c_str(), nullptr, 16);
        bytes.push_back(byte);
    }
    return bytes;
}

// AES-256-CBC 加密
vector<unsigned char> aes_encrypt(const string& plaintext, const string& key, const string& iv)
{
    vector<unsigned char> ciphertext(plaintext.size() + EVP_MAX_BLOCK_LENGTH);
    int len;
    int ciphertext_len;

    EVP_CIPHER_CTX* ctx = EVP_CIPHER_CTX_new();
    EVP_EncryptInit_ex(ctx, EVP_aes_256_cbc(), nullptr,
        (const unsigned char*)key.data(), (const unsigned char*)iv.data());

    EVP_EncryptUpdate(ctx, ciphertext.data(), &len,
        (const unsigned char*)plaintext.data(), plaintext.size());
    ciphertext_len = len;

    EVP_EncryptFinal_ex(ctx, ciphertext.data() + len, &len);
    ciphertext_len += len;

    EVP_CIPHER_CTX_free(ctx);
    ciphertext.resize(ciphertext_len);
    return ciphertext;
}

// 生成随机 key/iv（32字节/16字节）
string random_bytes(int length)
{
    string buf(length, '\0');
    RAND_bytes((unsigned char*)&buf[0], length);
    return buf;
}

int main()
{
    // 支持中文输入
    setlocale(LC_ALL, "");
    string key = "peacepeacebutthereisnopeace"; // 256-bit key
    while (true) {
        string input;
        cout << "请输入要加密的文本（支持中文）：";
        getline(cin, input);
        string iv = random_bytes(16); // 128-bit IV
        cout << "IV:\n" << toHex(vector<unsigned char>(iv.begin(), iv.end())) << endl;
        // 加密
        vector<unsigned char> encrypted = aes_encrypt(input, key, iv);
        // 输出十六进制
        cout << "加密结果:\n" << toHex(encrypted) << endl;
    }
    return 0;
}
